#pragma once

#include "google/protobuf/service.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/InetAddress.h"
#include "muduo/net/TcpServer.h"
#include "jsonUtils.h"

#define ME_TEST RpcProvider

class RpcProvider
{
private:
    /* data */
    bool getDetailMethod(std::string &serviceName,
                         std::string &methodName,
                         google::protobuf::Service *&currService,
                         const google::protobuf::MethodDescriptor *&currMethod,
                         int formatInt);
    bool executeMethod(google::protobuf::Service *&currService,
                       const google::protobuf::MethodDescriptor *&currMethod,
                       std::string &argStr,
                       const muduo::net::TcpConnectionPtr &ptr,
                       int formatInt);
    void sendResponse(const muduo::net::TcpConnectionPtr &, google::protobuf::Message *);

    // json
    void executeJsonMethod(std::string &serviceName,
                                  std::string &methodName,
                                  std::string &argStr,
                                  const muduo::net::TcpConnectionPtr &ptr);

    // protobuff
    using Methods = std::unordered_map<std::string, const google::protobuf::MethodDescriptor *>;
    struct ServiceInfo
    {
        google::protobuf::Service *_service;
        Methods _methods;
    };

    // json
    static std::unordered_map<std::string, std::unique_ptr<JsonService>> &getServiceJsonMap()
    {
        // 局部静态变量确保初始化顺序安全
        static std::unordered_map<std::string, std::unique_ptr<JsonService>> serviceMap;
        return serviceMap;
    }

public:
    // protobuff 感觉结构可以优化的更好

    std::unordered_map<std::string, ServiceInfo> _serviceMap;

    // json
    using JsonMethods = std::unordered_map<std::string, std::function<void(RpcJsonParam &)>>;

    template <typename T>
    class StrategyRegistry
    {
    public:
        StrategyRegistry(const std::string &name)
        {
            // 如果_serviceJsonMap没有初始化，则初始化
            std::cout << "name: " << name << "start regis" << std::endl;
            getServiceJsonMap().insert({name, std::make_unique<T>()});
        }
    };

    muduo::net::EventLoop _loop;
    // 将传入的service信息存储起来，格式(类似)：
    // {
    //     serviceName01:{
    //         _service:{/* 具体的service信息 */}
    //         _method:{
    //             method01 : {/* 具体的method信息 */}
    //         }
    //     },
    // },
    void notifyService(google::protobuf::Service *service);
    void run();

    void setConnectionCallback(const muduo::net::TcpConnectionPtr &);
    void setMessageCallback(const muduo::net::TcpConnectionPtr &,
                            muduo::net::Buffer *,
                            muduo::Timestamp);

    RpcProvider(/* args */);
    ~RpcProvider();
};
